<template>
  <el-upload
    class="image-uploader"
    v-loading="isUploading"
    :element-loading-text="elementLoadingText"
    ref="uploader"
    :limit="1"
    :action="action"
    :headers="headers"
    :on-success="onUploadSuccess"
    :before-upload="onBeforeUpload"
    :on-error="onUploadError"
    :on-remove="onUploadRemove"
    :accept="accept"
    :on-change="onUploadChange"
    :on-exceed="onExceed"
    :show-file-list="false"
    :disabled="!!fileUri"
    :data="content"
  >
    <slot>
      <div v-if="fileUri" class="image">
        <el-image
          ref="image"
          fit="cover"
          :preview-src-list="[fileUri]"
          :src="fileUri"
        >
          <div
            slot="placeholder"
            v-loading="true"
            element-loading-text="图片加载中..."
            class="image-slot image"
          ></div>
          <div slot="error" class="image-slot image">
            <i class="el-icon-picture-outline"></i>
          </div>
        </el-image>
        <i class="el-icon-close delete" @click.stop="deleteFile"></i>
        <el-alert
          v-if="imageError"
          :title="imageError"
          type="error"
          effect="dark"
          :closable="false"
          class="error"
        >
        </el-alert>
      </div>

      <div v-else class="image-uploader-icon">
        <slot name="placeholder">
          <i class="el-icon-plus"></i>
        </slot>
      </div>
    </slot>
  </el-upload>
</template>

<script>
import loadImage from 'blueimp-load-image/js/index'
export default {
  props: {
    imageSpecs: {
      type: Object
    },
    imagePath: {
      type: String,
      default: null
    },
    elementLoadingText: {
      type: String,
      default: '图片上传中...'
    },
    uploadTips: {
      type: String,
      default: ''
    },
    maxFileSize: {
      type: Number,
      default: 1024 * 1024 * 20
    },
    accept: {
      Type: String,
      default: '*'
    },
    headers: {
      type: Object,
      default: () => {}
    },
    action: {
      type: String,
      default: ''
    },
    fileSuffixs: {
      type: Array,
      default: () => ['*']
    },
    data: {
      type: Object
    },
    domain: {
      type: String
    },
    resKey: {
      type: String,
      default: () => 'key'
    },
    catelog: String
  },
  data () {
    return {
      header: null,
      fileUri: null,
      imageError: null,
      isUploading: false
    }
  },
  watch: {
    imagePath: {
      handler (val) {
        this.fileUri = val
      },
      immediate: true
    },
    data: {
      handler (val) {
        this.content = val
      },
      immediate: true
    }
  },
  methods: {
    onBeforeUpload (file) {
      console.debug('onBeforeUpload:file', file)
      console.debug('onBeforeUpload:catelog', this.catelog)

      return new Promise((resolve, reject) => {
        this.imageError = null
        this.isUploading = true
        // this.$refs.uploader.$el.children[1].style.display = this.display
        const name = file.name

        let result = true

        if (this.fileSuffixs.includes('*')) {
        } else {
          if (name && name.split(',').length > 0) {
            const suffix = name.split('.').pop()
            if (this.fileSuffixs.find((i) => i === suffix)) {
              if (file.size > this.maxFileSize) {
                this.$message.error(
                  `文件大小不能超过${this.renderSize(this.maxFileSize)}！`
                )
                result = false
              }
            } else {
              this.$message.error(
                `只能上传${this.fileSuffixs.join('|')}文件！`
              )
              result = false
            }
          } else {
            this.$message.error('请上传正确的文件')
            result = false
          }
        }

        if (result) {
          loadImage(file, { meta: true })
            .then((imageInfo) => {
              console.debug('imageINfo', imageInfo)
              if (imageInfo && imageInfo.exif) {
                const exif = imageInfo.exif

                var imgWidth = this.imageSpecs.width
                var imgHeight = this.imageSpecs.height
                var requireSize = 2
                var requreDpi = this.imageSpecs.dpi
                // 判断文件DPI

                // 校验分辨率单位
                var dpiUnit = exif.get('ResolutionUnit')
                if (!dpiUnit || (dpiUnit && dpiUnit > 0 && dpiUnit !== 2)) {
                  this.imageError = '分辨率单位错误'
                }
                var fDpi = exif.get('XResolution')
                console.debug('file_dpi :', fDpi)
                if (!fDpi || (fDpi && fDpi !== requreDpi && fDpi !== 300)) {
                  this.imageError = `当前分辨率 ${fDpi || '未识别'} 分辨率不符合要求 DPI要求: ${requreDpi}`
                }

                if ((imgWidth === 0 && imgHeight === 0) || requireSize === 0) {
                }

                // 判断文件尺寸

                var cImgWidth = imageInfo.originalWidth

                var cImgHeight = imageInfo.originalHeight

                if (cImgWidth === 0 && cImgHeight === 0) {
                  return true
                }

                if (requireSize === 1) {
                  if (
                    Math.abs(parseInt(cImgWidth) - parseInt(imgWidth)) > 10 ||
                    Math.abs(parseInt(cImgHeight) - parseInt(imgHeight)) > 10
                  ) {
                    if (
                      Math.abs(
                        parseInt(cImgWidth) - parseInt(imgWidth * 1.18)
                      ) > 50 ||
                      Math.abs(
                        parseInt(cImgHeight) - parseInt(imgHeight * 1.18)
                      ) > 50
                    ) {
                      this.imageError = `尺寸错误: 图片 ${cImgWidth}:${cImgHeight} 要求 ${imgWidth}:${imgHeight}`
                    }
                  }
                } else if (requireSize === 2) {
                  if (
                    !(
                      (Math.abs(parseInt(cImgWidth) - parseInt(imgWidth)) <
                        10 &&
                        Math.abs(parseInt(cImgHeight) - parseInt(imgHeight)) <
                          10) ||
                      (Math.abs(parseInt(cImgWidth) - parseInt(imgHeight)) <
                        10 &&
                        Math.abs(parseInt(cImgHeight) - parseInt(imgWidth)) <
                          10)
                    )
                  ) {
                    if (
                      !(
                        (Math.abs(
                          parseInt(cImgWidth) - parseInt(imgWidth * 1.18)
                        ) < 50 &&
                          Math.abs(
                            parseInt(cImgHeight) - parseInt(imgHeight * 1.18)
                          ) < 50) ||
                        (Math.abs(
                          parseInt(cImgWidth) - parseInt(imgHeight * 1.18)
                        ) < 50 &&
                          Math.abs(
                            parseInt(cImgHeight) - parseInt(imgWidth * 1.18)
                          ) < 50)
                      )
                    ) {
                      this.imageError = `尺寸错误: 图片 ${cImgWidth}:${cImgHeight} 要求 ${imgWidth}:${imgHeight}`
                    }
                  }
                }
              } else {
                this.imageError = '图片信息未识别'
              }

              if (this.imageError) {
                reject(new Error(this.imageError))
              } else {
                this.content.key = this.catelog + file.name

                resolve(file)
              }
            })
            .catch(() => {
              reject(new Error(this.imageError))
            })
        } else {
          reject(new Error(this.imageError))
        }
      })
    },
    onUploadChange (file, fileList) {
      console.debug('onUploadChange', file)
      this.isUploading = false
      this.fileUri = URL.createObjectURL(file.raw)
      this.$emit('onUploadChange', file)
    },
    onUploadSuccess (res, file) {
      console.debug('onUploadSuccess')
      this.fileUri = this.domain
        ? this.domain + res[this.resKey]
        : res[this.resKey]
      this.$emit('update:imagePath', this.fileUri)
    },
    onUploadError (err, file, fileList) {
      console.debug('onUploadError')
      let errMessage = '上传失败，请稍后重试'
      let error
      try {
        err && (error = JSON.parse(err.message))
        switch (err.status) {
          case 400:
            errMessage = '错误的请求'
            break
          case 401:
            this.$store.dispatch('FedLogOut')
            errMessage =
              error && error.msg
                ? error.msg
                : error.message
                  ? error.message
                  : '登录已超时，请重新登录'
            this.$router.replace({
              name: 'login',
              params: {
                lastPath: this.$router.history.current.fullPath
              }
            })
            break
          case 403:
            errMessage =
              error && error.message
                ? `你没有「${error.message}」的权限`
                : '未授权请求'
            break
          case 404:
            errMessage = '请求的资源不存在'
            break
          case 500:
            errMessage = '服务器内部错误'
            break
        }
      } catch (e) {}

      this.$message({
        message: errMessage,
        type: 'error'
      })
    },
    deleteFile () {
      this.fileUri = null
      this.$refs.uploader.clearFiles()
      this.$emit('update:imagePath', null)
    },
    onUploadRemove (file) {
      console.debug('onUploadRemove', file)
      this.isUploading = false
      if (file && file.status === 'success') {
        this.fileUri = null
        this.$refs.uploader.clearFiles()
        this.$emit('update:imagePath', null)
      }
    },
    onExceed (files, fileList) {
      console.debug('onExceed')
    },
    onDownload () {
      this.$emit('download', this.fileUri)
    },
    renderSize (value) {
      if (value == null || value === '') {
        return '0 Bytes'
      }
      var unitArr = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
      var index = 0
      var srcsize = parseFloat(value)
      index = Math.floor(Math.log(srcsize) / Math.log(1024))
      var size = srcsize / Math.pow(1024, index)
      size = size.toFixed(2) // 保留的小数位数
      return size + unitArr[index]
    }
  },
  computed: {
    uploadTipsText () {
      if (this.fileSuffixs.includes('*')) {
        return `文件大小不超过${this.renderSize(this.maxFileSize)}`
      }
      return `只能上传${this.fileSuffixs.join(
        '|'
      )}文件,且文件大小不超过${this.renderSize(this.maxFileSize)}`
    }
  }
}
</script>

<style lang="scss">
.image-uploader {
  display: inline-block;
  width: 180px;
  height: 180px;
}

.image-uploader .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.image-uploader .el-upload:hover {
  border-color: #409eff;
}
.image-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 180px;
  height: 180px;
  line-height: 180px;
  text-align: center;
}
.image {
  width: 180px;
  height: 180px;
  display: inline-block;
  position: relative;

  .el-image {
    width: 180px;
    height: 180px;
  }
  .delete {
    font-weight: bold;
    position: absolute;
    right: 0;
    top: 0;
    z-index: 999;
    margin-right: 5px;
    margin-top: 5px;
  }

  .error {
    position: absolute;
    bottom: 0;
    z-index: 999;
  }
}
</style>
